﻿using ComUIControl;
using KInterfaces;
using KXmlUIControl;
using LogLib;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;

namespace KFormBase
{
    /// <summary>
    /// 应用程序模块进程对象
    /// </summary>
    public class ModuleApplication : IDisposable
    {
        #region static Fields and Functions

        public static string XmlConfigFolder = "";

        static ModuleApplication()
        {
            string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
            directory = directory.Substring(6);
            StaticTypes.SetRootDirectory(directory);
            XmlConfigFolder = directory + @"\module\config";
        }
        #endregion

        /// <summary>
        /// 最新错误信息
        /// </summary>
        public string Error { get; private set; }

        protected string _xmlConfigFile = "";

        public string ApplicationName { get; private set; }

        public ModuleAppManager ModuleManager = null;

        public PageManager _pm = PageManager.Instance;

        private XmlConfigModule _xmlConfig = null;

        private XmlModuleObject _config = new XmlModuleObject();

        protected List<XmlPageObject> ListConfigPages = new List<XmlPageObject>();

        protected List<ModulePage> ListPages = new List<ModulePage>();

        protected LinkedList<ModulePage> LinkedPages = new LinkedList<ModulePage>();

        protected LinkedListNode<ModulePage> theNode = null;

        protected Stack<ModulePage> OpenPagesStack = new Stack<ModulePage>();

        /// <summary>
        /// 默认节点
        /// </summary>
        protected LinkedListNode<ModulePage> theDefaultNode = null;

        /// <summary>
        /// 主页节点
        /// </summary>
        protected LinkedListNode<ModulePage> theHomeNode = null;

        /// <summary>
        /// 业务开始节点
        /// </summary>
        protected LinkedListNode<ModulePage> theStartingNode = null;

        /// <summary>
        /// 上一个页面节点（用于实现上一步操作）
        /// </summary>
        protected ModulePage theLastPage = null;

        /// <summary>
        /// 当前模块应用程序的主页面
        /// </summary>
        public ModulePage HomePage
        {
            get { return theHomeNode.Value; }
        }

        /// <summary>
        /// 当前模块应用程序的业务开始页面
        /// </summary>
        public ModulePage StartingPage
        {
            get { return theStartingNode.Value; }
        }

        /// <summary>
        /// 用于在应用程序模块页面之间共享数据
        /// </summary>
        public ShareData SharedData { get; private set; }

        public KJob CurrentJob
        {
            get;
            private set;
        }

        public KJob CreatNewJob(string name)
        {
            CurrentJob = KJobFactory.StartNew(_config.Name, name, Guid.NewGuid().ToString("N"));
            return CurrentJob;
        }

        public string[] PageDirectoryArray = null;

        public bool IsFirstPage
        {
            get { return theNode == LinkedPages.First; }
        }

        public bool IsLastPage
        {
            get { return theNode == LinkedPages.Last; }
        }

        ///// <summary>
        ///// 针对用户使用时序，打开的上一个的流程页面
        ///// </summary>
        //private ModulePage LastUsedPage;

        /// <summary>
        /// 当前页面流程
        /// </summary>
        public ModulePage CurrentPage
        {
            get
            {
                return theNode.Value;
            }
        }

        /// <summary>
        /// 窗体通用风格配置文件路径
        /// </summary>
        public string UsualStyleConfigPath;

        /// <summary>
        /// 当前语言代码
        /// </summary>
        private string _languageCode = "zh-CN";
        public string LanguageCode
        {
            get
            {
                return _languageCode;
            }
        }

        #region public Events

        /// <summary>
        /// 当前语言改变事件
        /// </summary>
        public event DelegateAppLanguageChanged AppLanguageChanged;
        public void OnLanguageChanged(string code)
        {
            if (_languageCode != code)
            {
                _languageCode = code;
                //各模块切换语言
                ApplyLanguage(code);
                //调用其它语言切换事件
                if (AppLanguageChanged != null)
                {
                    AppLanguageChanged(code);
                }
            }
        }

        /// <summary>
        /// 当前模块页面切换事件
        /// </summary>
        public event ModulePageChangeEventHandler ModulePageChanged;
        protected void OnModulePageChanged()
        {
            //页面跳转（切换）事件
            if (ModulePageChanged != null)
            {
                ModulePageChanged(this, new ModulePageChangedEventArgs(CurrentPage));
                OnNewPageStarted();
            }
        }

        /// <summary>
        /// 当前模块页面切换事件
        /// </summary>
        public event ModuleAppSwitchedEventHandler ModuleAppSwitched;
        protected void OnModuleAppSwitched(ModuleApplication app)
        {
            //模块应用（切换）事件
            if (ModuleAppSwitched != null)
            {
                ModuleAppSwitched(this, new ModuleAppSwitchedEventArgs(app));
            }
        }

        /// <summary>
        /// 当执行管理员动作事件
        /// </summary>
        public event TakeAdministratorActionEventHandler AdminActionTaken;
        public void OnAdminActionTaken(AdministratorAction action)
        {
            //管理员动作执行事件
            if (AdminActionTaken != null)
            {
                AdminActionTaken(this, new AdministratorActionTakenEventArgs(action));
            }
        }

        /// <summary>
        /// 当业务状态变化事件
        /// </summary>
        public event JobStateChangedEventHandler JobStateChanged;
        protected void OnJobStateChanged(JobStateChangedEventArgs e)
        {
            //业务状态变化执行事件
            if (JobStateChanged != null)
            {
                JobStateChanged(this, e);
            }
        }

        /// <summary>
        /// 请求关闭应用程序事件
        /// </summary>
        public event EventHandler AppExitRequested;
        public void OnAppExitRequested()
        {
            if (AppExitRequested != null)
            {
                AppExitRequested(null, null);
            }
        }

        /// <summary>
        /// 关闭应用程序事件
        /// </summary>
        public event EventHandler AppExited;
        public void OnAppExited()
        {
            if (AppExited != null)
            {
                AppExited(null, null);
            }
        }

        #endregion

        public ModuleApplication()
        {

        }

        public ModuleApplication(ShareData data, XmlModuleObject config)
        {
            this.SharedData = data;
            this._config = config;
            this.ApplicationName = _config.Name;
        }

        private bool LoadConfig()
        {
            Log.WriteAsync("LoadConfig in");
            PageDirectoryArray = _config.Directory.Split(new char[2] { ';', ' ' });
            _xmlConfigFile = string.Format(@"{0}\{1}.xml", XmlConfigFolder, _config.Name);
            if (!File.Exists(_xmlConfigFile))
            {
                Error = "配置文件不存在:" + _xmlConfigFile;
                Log.WriteAsync(Error);
                return false;
            }
            _xmlConfig = new XmlConfigModule(_xmlConfigFile);
            if (!_xmlConfig.OnReading())
            {
                Error = _xmlConfig.Error;
                Log.WriteAsync(Error);
                return false;
            }
            ListConfigPages = _xmlConfig.ListPages;
            Log.WriteAsync("InitializeCustomComponent out");
            return true;
        }

        public bool Init()
        {
            LinkedPages.Clear();
            OpenPagesStack.Clear();
            LinkedListNode<ModulePage> theNewNode = null;
            if (!LoadConfig())
            {
                return false;
            }
            if (!_pm.Init(ListConfigPages))
            {
                Error = _pm.Error;
                Log.WriteAsync(Error);
                return false;
            }
            foreach (XmlPageObject config in ListConfigPages)
            {
                ModulePage newPage = _pm[config.TypeName];
                if (!newPage.Available)
                {
                    Error = $"应用程序模块{ApplicationName}加载页面错误:\n{newPage.Error}";
                    Log.WriteAsync(Error);
                    return false;
                }
                ListPages.Add(newPage);
                if (config.Enable)
                {
                    theNewNode = LinkedPages.AddLast(newPage);
                    if (theHomeNode == null && config.TypeName.Equals(_xmlConfig.HomePageName))
                    {
                        theHomeNode = theNewNode;
                    }
                    else if (theStartingNode == null && config.TypeName.Equals(_xmlConfig.StartingPageName))
                    {
                        theStartingNode = theNewNode;
                    }
                }
            }
            //theNode = theHomeNode;
            if (theHomeNode == null)
            {
                Error = "未发现主页，\n请核查配置文件是否正确.";
                Log.WriteAsync(Error);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 启动业务流程，显示第一个页面
        /// </summary>
        public void Restart()
        {
            SharedData.ClearValue();
            ToHomePage();
        }

        /// <summary>
        /// 转到启动页面
        /// </summary>
        public void OnStartup()
        {
            ClearPages();
            theNode = LinkedPages.First;
            OnModulePageChanged();
        }

        /// <summary>
        /// 结束上一个页面
        /// </summary>
        private void OnLastPageStopped()
        {
            if (theNode != null)
            {
                ModulePage page = theNode.Value;
                page.Stop();
            }
        }

        /// <summary>
        /// 启动新页面
        /// </summary>
        private void OnNewPageStarted()
        {
            if (theNode != null)
            {
                ModulePage page = theNode.Value;
                page.Start(this);
            }
        }

        /// <summary>
        /// 转到系统主页
        /// </summary>
        public void ToHomeApp()
        {
            if (theNode != null && theNode.Value.SID == theHomeNode.Value.SID)
            {
                return;
            }
            OnLastPageStopped();
            if (CurrentJob != null)
            {
                CurrentJob.StateChanged -= OnJobStateChanged;
            }
            CurrentJob = null;
            ClearPages();
            theNode = theHomeNode;

            OnModuleAppSwitched(ModuleManager.HomeApp);
        }

        /// <summary>
        /// 转到系统主页
        /// </summary>
        public void ToDefaultApp()
        {
            //if (theNode != null && theNode.Value.SID == theHomeNode.Value.SID)
            //{
            //    return;
            //}
            OnLastPageStopped();
            ClearPages();
            theNode = theHomeNode;
            OnModuleAppSwitched(ModuleManager.DefaultApp);
        }

        /// <summary>
        /// 转到任何一个可用的应用程序模块
        /// </summary>
        /// <param name="moduleName">指定跳转模块应用程序的名称</param>
        public void ToAnyApp(string moduleName)
        {
            if (theNode != null && theNode.Value.SID == theHomeNode.Value.SID)
            {
                return;
            }
            OnLastPageStopped();
            theNode = theHomeNode;
            try
            {
                ModuleApplication selectApp = ModuleManager[moduleName];
                OnModuleAppSwitched(selectApp);
            }
            catch (Exception ex)
            {
                string strLog = string.Format("模块切换错误:找不到目标{0}, 详情:{1}", moduleName, ex.Message);
                Log.WriteAsync(strLog);
                MessageBox.Show(strLog);
            }
        }

        public void StartNew(string name, string id, string inParams = "")
        {
            OnLastPageStopped();
            CurrentJob = KJobFactory.StartNew(_config.Name, name, id, inParams);
            CurrentJob.StateChanged += OnJobStateChanged;
            ToStartingPage();
        }

        /// <summary>
        /// 转到模块应用程序的主页
        /// </summary>
        private void ToHomePage()
        {
            OpenPagesStack.Clear();
            theLastPage = null;
            theNode = theHomeNode;
            OpenPagesStack.Push(theNode.Value);
            OnModulePageChanged();
        }

        /// <summary>
        /// 转到模块应用程序的业务开始页面
        /// </summary>
        private void ToStartingPage()
        {
            if (theNode != null && theNode.Value.SID == theStartingNode.Value.SID)
            {
                return;
            }
            OpenPagesStack.Clear();
            theNode = theStartingNode;
            OpenPagesStack.Push(theNode.Value);
            OnModulePageChanged();
        }

        private ModulePage GetLastPage()
        {
            if (OpenPagesStack.Count > 0)
            {
                return OpenPagesStack.Peek();
            }
            else
            {
                return null;
            }
        }

        private bool PopPage(out LinkedListNode<ModulePage> lastOpenNode)
        {
            lastOpenNode = null;
            if (OpenPagesStack.Count == 0)
            {
                return false;
            }
            ModulePage page0 = OpenPagesStack.Peek();
            ModulePage page1 = theNode.Value;
            if (page0.MainPageType == page1.MainPageType)
            {
                OpenPagesStack.Pop();
            }
            ModulePage lastOpenPage = OpenPagesStack.Peek();
            LinkedListNode<ModulePage> node = LinkedPages.First;
            while (node != null)
            {
                if (lastOpenPage.MainPageType == node.Value.MainPageType)
                {
                    lastOpenNode = node;
                    return true;
                }
                else
                {
                    node = node.Next;
                }
            }
            return false;
        }

        private void SetLastPage(LinkedListNode<ModulePage> node)
        {
            //这六个弹出框不记录到下一步
            if (node.Value.Config.TypeName.Equals("YSLPages.PageApplyPassportInfo") ||
                node.Value.Config.TypeName.Equals("YSLPages.PageApplyGAZInfo") ||
                node.Value.Config.TypeName.Equals("YSLPages.PageApplyGAQZ") ||
                node.Value.Config.TypeName.Equals("YSLPages.PageApplyTWZInfo") ||
                node.Value.Config.TypeName.Equals("YSLPages.PageApplyTWQZ"))
            {
                return;
            }

            //从上述六个弹窗返回到证件类型选择的时候，不记录，否则该页的上一步则无法使用
            if (theNode.Value.Config.TypeName.Equals("YSLPages.PageApplyPassportInfo") ||
                theNode.Value.Config.TypeName.Equals("YSLPages.PageApplyGAZInfo") ||
                theNode.Value.Config.TypeName.Equals("YSLPages.PageApplyGAQZ") ||
                theNode.Value.Config.TypeName.Equals("YSLPages.PageApplyTWZInfo") ||
                theNode.Value.Config.TypeName.Equals("YSLPages.PageApplyTWQZ"))
            {
                return;
            }
            theLastPage = node.Value;
        }

        private bool FindLastPage(ModulePage lastPage, out LinkedListNode<ModulePage> lastOpenNode)
        {
            lastOpenNode = null;
            if (lastPage == null)
                return false;

            LinkedListNode<ModulePage> node = LinkedPages.First;
            while (node != null)
            {
                if (lastPage.MainPageType == node.Value.MainPageType)
                {
                    lastOpenNode = node;
                    return true;
                }
                else
                {
                    node = node.Next;
                }
            }
            return false;
        }

        private bool HasOpenPage(ModulePage checkPage)
        {
            //ModulePage currentPage = theNode.Value;
            ModulePage[] pages = OpenPagesStack.ToArray();
            for (int i = 0; i < pages.Length; i++)
            {
                ModulePage page = pages[i];
                if (page.MainPageType == checkPage.MainPageType)
                {
                    return true;
                }
            }
            return false;
        }

        private void PushPage()
        {
            ModulePage lastPage = GetLastPage();
            ModulePage currentPage = theNode.Value;
            if (lastPage == null)
            {
                OpenPagesStack.Push(theNode.Value);
                return;
            }
            if (lastPage.Pos < currentPage.Pos)
            {
                OpenPagesStack.Push(theNode.Value);
                return;
            }
            if (!HasOpenPage(CurrentPage))
            {
                OpenPagesStack.Push(theNode.Value);
            }
            else
            {
                Log.WriteAsync(string.Format("意外: 发现页面{0}已经打开过.", theNode.Value.MainPageType));
            }
        }

        /// <summary>
        /// 转到最后一个可用的模块
        /// </summary>
        public void ToEndPage()
        {
            if (theNode != LinkedPages.Last)
            {
                theNode = LinkedPages.Last;
                OnModulePageChanged();
                PushPage();
            }
        }

        /// <summary>
        /// 转到上一页
        /// </summary>
        public void ToLastPage()
        {
            //if (theNode.Previous == null)
            //{
            //    return;
            //}
            //if (theNode == theHomeNode)
            //{
            //    return;
            //}
            //if (theNode != LinkedPages.First)
            //{             
            //    // add by linden 2021-08-14 21:21
            //    LinkedListNode<ModulePage> lastPageNode = null;
            //    if (PopPage(out lastPageNode))
            //    {
            //        theNode = lastPageNode;
            //        OnModulePageChanged();
            //        PushPage();
            //    }
            //}
            //else
            //{
            //    ToHomePage();
            //}
            if (theLastPage == null)
            {
                return;
            }

            if (theLastPage == theHomeNode.Value)
            {
                return;
            }

            if (FindLastPage(theLastPage, out LinkedListNode<ModulePage> lastPageNode))
            {
                theNode = lastPageNode;
                OnModulePageChanged();
                PushPage();
            }
            else
            {
                ToHomePage();
            }
        }

        /// <summary>
        /// 转到下一页
        /// </summary>
        public void ToNextPage()
        {
            if (theNode == LinkedPages.Last
               || theNode.Next == null)
            {
                ToHomePage();
                return;
            }

            SetLastPage(theNode);
            theNode = theNode.Next;
            OnModulePageChanged();
            PushPage();
        }

        /// <summary>
        /// 转到任何一个可用的模块页面
        /// </summary>
        /// <param name="pageName">指定跳转页面类的完全限定名称</param>
        public void ToAnyPage(string pageName)
        {
            ModulePage lastPage = CurrentPage;
            if (lastPage.MainPageType.FullName == pageName)
            {
                return;
            }
            bool find = false;
            LinkedListNode<ModulePage> node = LinkedPages.First;
            while (node != null)
            {
                ModulePage page = node.Value;
                if (page.Config.TypeName.Equals(pageName))
                {
                    find = true;
                    OnLastPageStopped();
                    SetLastPage(theNode);
                    theNode = node;
                    Log.WriteAsync("找到了页面:" + pageName);
                    break;
                }
                node = node.Next;
            }
            if (find)
            {
                if (HasOpenPage(lastPage))
                {
                    LinkedListNode<ModulePage> lastPageNode = null;
                    if (!PopPage(out lastPageNode))
                    {
                        Log.WriteAsync($"弹出上一个页面失败:{lastPage.MainPageType.ToString()}");
                    }
                }
                OnModulePageChanged();
                PushPage();
            }
            else
            {
                string strLog = string.Format("找不到名称为{0}的页面.", pageName);
                Log.WriteAsync(strLog);
                MsgBox.Show(strLog);
            }
        }

        /// <summary>
        /// 销毁应用程序
        /// </summary>
        /// <returns></returns>
        public void Dispose()
        {
            if (ListPages == null || ListPages.Count == 0)
                return;
            foreach (ModulePage page in ListPages)
            {
                if (page != null && !page.Disposed)
                {
                    page.Dispose();
                }
            }
        }

        /// <summary>
        /// 清理所有页面数据
        /// </summary>
        public void ClearPages()
        {
            for (int i = 0; i < ListPages.Count; i++)
            {
                IPageProcess p = ListPages[i].MainPageProcess;
                if (p != null)
                {
                    p.ClearData();
                }
                IPageProcess p1 = ListPages[i].ChildPageProcess;
                if (p1 != null)
                {
                    p1.ClearData();
                }
            }
        }

        /// <summary>
        /// 应用指定的语言
        /// </summary>
        /// <param name="LanguageCode"></param>
        public void ApplyLanguage(string LanguageCode)
        {
            CultureInfo m_ci = new CultureInfo(LanguageCode);
            Thread.CurrentThread.CurrentCulture = m_ci;
            Thread.CurrentThread.CurrentUICulture = m_ci;
            LinkedListNode<ModulePage> node = LinkedPages.First;
            while (node != null)
            {
                ModulePage page = node.Value;
                if (page != null)
                {
                    page.ApplyLanguage(LanguageCode);
                }
                node = node.Next;
            }
        }

        #region PageProcess EventHandler 
        public void OnPageChanged(object sender, PageChangedEventArgs e)
        {
            OnLastPageStopped();
            switch (e.Direction)
            {
                case PageTo.Home:
                    ToHomePage();
                    break;
                case PageTo.Starting:
                    ToStartingPage();
                    break;
                case PageTo.Next:
                    ToNextPage();
                    break;
                case PageTo.Last:
                    ToLastPage();
                    break;
                case PageTo.End:
                    ToEndPage();
                    break;
                case PageTo.Any:
                    break;
                default:
                    break;
            }
        }

        public void OnPageSwitched(object sender, PageSwitchedEventArgs e)
        {
            ToAnyPage(e.PageName);
        }

        public void OnModuleChanged(object sender, ModuleChangedEventArgs e)
        {
            switch (e.Direction)
            {
                case ModuleAppTo.Home:
                    ToHomeApp();
                    break;
                case ModuleAppTo.Default:
                    ToDefaultApp();
                    break;
                case ModuleAppTo.Any:
                    break;
                default:
                    break;
            }
        }

        public void OnModuleSwitched(object sender, ModuleSwitchedEventArgs e)
        {
            ToAnyApp(e.ModuleName);
        }

        public void TakeAdministratorAction(object sender, AdministratorActionTakenEventArgs e)
        {
            OnAdminActionTaken(e.Action);
        }

        public void OnJobStateChanged(object sender, JobStateChangedEventArgs e)
        {
            OnJobStateChanged(e);
        }
        #endregion
    }
}
